/**
 * Element Plus全局配置修复
 * @author Wu.Liang
 * @date 2025-01-30
 * @updated 2025-01-30 - 增强错误处理和DOM安全检查，减少警告信息
 */

import { ElConfigProvider } from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn'

// 全局状态管理
let isFixApplied = false
let warningCount = 0
const MAX_WARNINGS = 10 // 限制警告数量

/**
 * 修复Element Plus的getBoundingClientRect问题
 */
export function fixElementPlusGetBoundingClientRect() {
  // 在DOM加载完成后执行修复
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', applyElementPlusFix)
  } else {
    applyElementPlusFix()
  }
}

/**
 * 应用Element Plus修复
 */
function applyElementPlusFix() {
  if (isFixApplied) {
    return
  }
  
  console.log('应用Element Plus getBoundingClientRect修复...')
  
  // 重写Element.prototype.getBoundingClientRect
  const originalGetBoundingClientRect = Element.prototype.getBoundingClientRect
  
  Element.prototype.getBoundingClientRect = function() {
    try {
      // 检查元素是否存在
      if (!this) {
        return createDefaultDOMRect()
      }
      
      // 检查元素是否是有效的Element
      if (!(this instanceof Element)) {
        return createDefaultDOMRect()
      }
      
      // 检查元素是否在DOM中
      if (!document.contains(this)) {
        return createDefaultDOMRect()
      }
      
      // 检查元素是否可见
      const style = window.getComputedStyle(this)
      if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
        return createDefaultDOMRect()
      }
      
      // 调用原始方法
      const rect = originalGetBoundingClientRect.call(this)
      
      // 检查元素是否有尺寸
      if (rect.width === 0 && rect.height === 0) {
        return createDefaultDOMRect()
      }
      
      return rect
    } catch (error) {
      // 只在开发环境下显示错误信息
      if (process.env.NODE_ENV === 'development' && warningCount < MAX_WARNINGS) {
        console.warn('Element Plus: getBoundingClientRect调用失败:', error)
        warningCount++
      }
      return createDefaultDOMRect()
    }
  }
  
  // 修复HTMLElement.prototype.getBoundingClientRect
  const originalHTMLElementGetBoundingClientRect = HTMLElement.prototype.getBoundingClientRect
  
  HTMLElement.prototype.getBoundingClientRect = function() {
    try {
      // 检查元素是否存在
      if (!this) {
        return createDefaultDOMRect()
      }
      
      // 检查元素是否是有效的HTMLElement
      if (!(this instanceof HTMLElement)) {
        return createDefaultDOMRect()
      }
      
      // 检查元素是否在DOM中
      if (!document.contains(this)) {
        return createDefaultDOMRect()
      }
      
      // 检查元素是否可见
      const style = window.getComputedStyle(this)
      if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
        return createDefaultDOMRect()
      }
      
      // 调用原始方法
      const rect = originalHTMLElementGetBoundingClientRect.call(this)
      
      // 检查元素是否有尺寸
      if (rect.width === 0 && rect.height === 0) {
        return createDefaultDOMRect()
      }
      
      return rect
    } catch (error) {
      // 只在开发环境下显示错误信息
      if (process.env.NODE_ENV === 'development' && warningCount < MAX_WARNINGS) {
        console.warn('Element Plus: HTMLElement getBoundingClientRect调用失败:', error)
        warningCount++
      }
      return createDefaultDOMRect()
    }
  }
  
  isFixApplied = true
  console.log('Element Plus getBoundingClientRect修复应用完成')
}

/**
 * 创建默认的DOMRect对象
 */
function createDefaultDOMRect(): DOMRect {
  return {
    x: 0,
    y: 0,
    width: 0,
    height: 0,
    top: 0,
    right: 0,
    bottom: 0,
    left: 0,
    toJSON: () => ({ x: 0, y: 0, width: 0, height: 0, top: 0, right: 0, bottom: 0, left: 0 })
  } as DOMRect
}

/**
 * 获取Element Plus全局配置
 */
export function getElementPlusConfig() {
  return {
    locale: zhCn,
    size: 'default' as const,
    zIndex: 3000,
    button: {
      autoInsertSpace: true
    },
    message: {
      max: 3
    },
    notification: {
      max: 3
    }
  }
}

/**
 * 创建Element Plus配置提供者
 */
export function createElementPlusConfigProvider() {
  return {
    name: 'ElementPlusConfigProvider',
    setup() {
      // 应用修复
      fixElementPlusGetBoundingClientRect()
      
      return {
        config: getElementPlusConfig()
      }
    }
  }
}

/**
 * 延迟初始化Element Plus组件
 */
export function delayElementPlusInit(component: any, delay: number = 100) {
  return new Promise((resolve) => {
    setTimeout(() => {
      try {
        if (component && typeof component.init === 'function') {
          component.init()
        }
        resolve(true)
      } catch (error) {
        if (process.env.NODE_ENV === 'development') {
          console.warn('延迟初始化Element Plus组件失败:', error)
        }
        resolve(false)
      }
    }, delay)
  })
}

/**
 * 安全地获取元素位置信息
 */
export function safeGetElementRect(element: Element | null | undefined): DOMRect {
  if (!element) {
    return createDefaultDOMRect()
  }
  
  try {
    // 检查元素是否在DOM中
    if (!document.contains(element)) {
      return createDefaultDOMRect()
    }
    
    // 检查元素是否可见
    const style = window.getComputedStyle(element)
    if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
      return createDefaultDOMRect()
    }
    
    return element.getBoundingClientRect()
  } catch (error) {
    if (process.env.NODE_ENV === 'development') {
      console.warn('获取元素位置信息失败:', error)
    }
    return createDefaultDOMRect()
  }
}

/**
 * 等待元素准备就绪
 */
export function waitForElementReady(selector: string, timeout: number = 5000): Promise<Element | null> {
  return new Promise((resolve) => {
    const startTime = Date.now()
    
    const checkElement = () => {
      const element = document.querySelector(selector)
      
      if (element) {
        // 检查元素是否完全渲染
        const rect = element.getBoundingClientRect()
        if (rect.width > 0 && rect.height > 0) {
          resolve(element)
          return
        }
      }
      
      // 检查超时
      if (Date.now() - startTime > timeout) {
        if (process.env.NODE_ENV === 'development') {
          console.warn(`等待元素 ${selector} 超时`)
        }
        resolve(null)
        return
      }
      
      // 继续等待
      requestAnimationFrame(checkElement)
    }
    
    checkElement()
  })
}

/**
 * 监听Element Plus组件错误
 */
export function listenElementPlusErrors() {
  // 监听全局错误
  window.addEventListener('error', (event) => {
    if (event.error && event.error.message && 
        (event.error.message.includes('getBoundingClientRect') || 
         event.error.message.includes('_a2.getBoundingClientRect'))) {
      if (process.env.NODE_ENV === 'development') {
        console.warn('检测到Element Plus getBoundingClientRect错误，应用修复...')
      }
      // 延迟应用修复
      setTimeout(() => {
        fixElementPlusGetBoundingClientRect()
      }, 50)
    }
  })
  
  // 监听未处理的Promise拒绝
  window.addEventListener('unhandledrejection', (event) => {
    if (event.reason && event.reason.message && 
        (event.reason.message.includes('getBoundingClientRect') || 
         event.reason.message.includes('_a2.getBoundingClientRect'))) {
      if (process.env.NODE_ENV === 'development') {
        console.warn('检测到Element Plus getBoundingClientRect Promise错误，应用修复...')
      }
      // 延迟应用修复
      setTimeout(() => {
        fixElementPlusGetBoundingClientRect()
      }, 50)
    }
  })
  
  // 监听Vue错误
  if (window.Vue) {
    const originalErrorHandler = window.Vue.config.errorHandler
    window.Vue.config.errorHandler = (error, vm, info) => {
      if (error.message && 
          (error.message.includes('getBoundingClientRect') || 
           error.message.includes('_a2.getBoundingClientRect'))) {
        if (process.env.NODE_ENV === 'development') {
          console.warn('检测到Vue中的Element Plus getBoundingClientRect错误，应用修复...')
        }
        setTimeout(() => {
          fixElementPlusGetBoundingClientRect()
        }, 50)
      }
      
      // 调用原始错误处理器
      if (originalErrorHandler) {
        originalErrorHandler(error, vm, info)
      }
    }
  }
}

// 声明全局Vue类型
declare global {
  interface Window {
    Vue?: {
      config: {
        errorHandler?: (error: Error, vm: any, info: string) => void
      }
    }
  }
} 